import 'dart:developer';

import 'package:edu/constants/config.dart';
import 'package:edu/pages/main_tab/edu/edu_page.dart';
import 'package:edu/utils/app_preferences.dart';
import 'package:edu/utils/database_helper.dart';
import 'package:flutter/material.dart';
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';

class EduCourseVideoPlayWidgetLogic extends ChangeNotifier {
  final int courseId;
  bool isDataRead = false;

  late final player = Player(
    configuration: const PlayerConfiguration(title: '课程媒体播放'),
  );
  late final controller = VideoController(player);

  bool _manualPostionChaning = false; // 是否手动修改进度
  bool _isPlaying = false; // 是否正在播放
  final positionProgress = ValueNotifier<Duration>(Duration.zero); // 当前播放进度
  final bufferPostionProgress = ValueNotifier<Duration>(Duration.zero); // 缓冲进度

  final videoIdNotifier = ValueNotifier<int>(0);
  final progressNotifier = ValueNotifier<double>(0.0);

  bool _updatePositionWhenPlaying = true;

  EduCourseVideoPlayWidgetLogic(this.courseId);

  void init() async {
    EduPage.activeCourseIdNotifier.value = 0;

    // 监听进度
    player.stream.position.listen(_updateVideoPostion);

    // 监听缓冲进度
    player.stream.buffer.listen((event) {
      bufferPostionProgress.value = event;
    });

    // 监听播放错误
    player.stream.error.listen((event) {
      log('播放错误: $event');
    });

    // 监听播放完成
    player.stream.completed.listen((event) {
      if (event) {
        final videoId = videoIdNotifier.value;
        final progress =
            (positionProgress.value.inMilliseconds /
                player.state.duration.inMilliseconds) *
            100;
        final milliseconds = positionProgress.value.inMilliseconds;
        // 插入播放进度
        DatabaseHelper.shared.insertVideoProgress(
          videoId,
          courseId,
          milliseconds,
          progress,
        );
      }
    });

    // 监听播放列表
    player.stream.playlist.listen((event) async {
      final medias = event.medias;
      if (medias.length == 2) {
        final media = event.medias[1]; // 播放列表
        final videoId = int.parse(media.uri.split('/').last); // 视频id
        videoIdNotifier.value = videoId;
        // 获取播放进度
        progressNotifier.value =
            await DatabaseHelper.shared.getVideoProgress(videoId) ?? 0;

        player.next();
        player.play();
        _updatePositionWhenPlaying = true;
        Future.delayed(Duration.zero, () async {
          player.remove(0);
        });
      } else if (medias.length == 1) {
        final media = event.medias[0];
        final videoId = int.parse(media.uri.split('/').last);
        videoIdNotifier.value = videoId;
        _updatePositionWhenPlaying = true;
        progressNotifier.value =
            await DatabaseHelper.shared.getVideoProgress(videoId) ?? 0;
      }

      if (isDataRead == false) {
        isDataRead = true;
        notifyListeners();
      }
    });

    // 播放进度监听
    player.stream.buffer.listen((event) async {
      if (_updatePositionWhenPlaying) {
        final videoId = videoIdNotifier.value;
        final progress = await DatabaseHelper.shared.getVideoProgress(videoId);
        if (progress != null) {
          final v = player.state.duration.inMilliseconds * progress / 100;
          await player.seek(Duration(milliseconds: v.toInt()));
        }
        _updatePositionWhenPlaying = false;
      }
    });
  }

  @override
  void dispose() {
    final videoId = videoIdNotifier.value;
    if (videoId != 0) {
      final progress =
          (positionProgress.value.inMilliseconds /
              player.state.duration.inMilliseconds) *
          100;
      final milliseconds = positionProgress.value.inMilliseconds;
      // 插入播放进度
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
        await DatabaseHelper.shared.insertVideoProgress(
          videoId,
          courseId,
          milliseconds,
          progress,
        );
        EduPage.activeCourseIdNotifier.value = courseId;
      });
    }

    player.dispose();
    super.dispose();
  }

  // 播放进度开始修改
  void videoPostionChangeStart(double value) {
    _manualPostionChaning = true;
    _isPlaying = player.state.playing;
    player.pause();
  }

  // 播放进度正在修改
  void videoPostionChange(double value) {
    positionProgress.value = Duration(milliseconds: value.round());
  }

  // 播放进度结束修改
  void videoPostionChangeEnd(double value) async {
    await player.seek(Duration(milliseconds: value.round()));
    _manualPostionChaning = false;
    if (_isPlaying) {
      player.play();
    }
  }

  // 播放进度更新
  void _updateVideoPostion(Duration v) {
    if (!_updatePositionWhenPlaying && !_manualPostionChaning) {
      positionProgress.value = v;
    }

    // 播放进度
    if (!_updatePositionWhenPlaying) {
      final duration = player.state.duration.inMilliseconds;
      if (duration == 0) {
        progressNotifier.value = 0.0;
      } else {
        progressNotifier.value = (v.inMilliseconds / duration) * 100;
      }
    }
  }

  // 创建第一个视频
  Future<void> makeFirstVideoMedia(int videoId) async {
    final token = AppPreferences.shared.userToken;
    if (token == null) {
      return;
    }

    final videoUrl = '${Config.baseVideoUrl}/v1/course/video/$videoId';
    final m = Media(videoUrl, httpHeaders: {'authorization': 'Bearer $token'});

    progressNotifier.value =
        await DatabaseHelper.shared.getVideoProgress(videoId) ?? 0;

    await player.open(m, play: false);
  }

  // 加载视频
  void loadVideo(int videoId) async {
    final token = AppPreferences.shared.userToken;
    if (token == null) {
      return;
    }

    await player.pause();

    final oldId = videoIdNotifier.value;
    if (oldId != 0) {
      final progress =
          (positionProgress.value.inMilliseconds /
              player.state.duration.inMilliseconds) *
          100;
      final milliseconds = positionProgress.value.inMilliseconds;
      await DatabaseHelper.shared.insertVideoProgress(
        oldId,
        courseId,
        milliseconds,
        progress,
      );
    }

    Future.delayed(Duration.zero, () async {
      bufferPostionProgress.value = Duration.zero;
      progressNotifier.value =
          await DatabaseHelper.shared.getVideoProgress(videoId) ?? 0;
      positionProgress.value = Duration.zero;

      final videoUrl = '${Config.baseVideoUrl}/v1/course/video/$videoId';
      final m = Media(
        videoUrl,
        httpHeaders: {'authorization': 'Bearer $token'},
      );
      await player.add(m);

      isDataRead = false;
      notifyListeners();
    });
  }
}
